<template>
  <div class="order-train">
    <span class="order-train-main">{{dailyTrainTicket.date}}</span>&nbsp;
    <span class="order-train-main">{{dailyTrainTicket.trainCode}}</span>次&nbsp;
    <span class="order-train-main">{{dailyTrainTicket.start}}</span>站
    <span class="order-train-main">({{dailyTrainTicket.startTime}})</span>&nbsp;
    <span class="order-train-main">——</span>&nbsp;
    <span class="order-train-main">{{dailyTrainTicket.end}}</span>站
    <span class="order-train-main">({{dailyTrainTicket.endTime}})</span>&nbsp;

    <div class="order-train-ticket">
      <span v-for="item in seatTypes" :key="item.type">
        <span>{{item.desc}}</span>：
        <span class="order-train-ticket-main">{{item.price}}￥</span>&nbsp;
        <span class="order-train-ticket-main">{{item.count}}</span>&nbsp;张票&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      </span>
    </div>

    <a-divider></a-divider>
    <b>勾选要购票的乘客:</b>&nbsp;
    <a-checkbox-group v-model:value="PassengerChecks" :options="PassengerOptions"/>
<!--    <br/>-->
<!--    选中的乘客:{{PassengerChecks}}-->
<!--    <br/>-->
<!--    购票列表:{{tickets}}-->
    <div class="order-tickets">
      <a-row class="order-tickets-header" v-if="tickets.length > 0">
        <a-col :span="3">乘客</a-col>
        <a-col :span="15">身份证</a-col>
        <a-col :span="3">票种</a-col>
        <a-col :span="3">座位类型</a-col>
      </a-row>
      <a-row class="order-tickets-row" v-for="ticket in tickets" :key="ticket.passengerId">
        <a-col :span="3">{{ticket.passengerName}}</a-col>
        <a-col :span="15">{{ticket.passengerIdCard}}</a-col>
        <a-col :span="3">
          <a-select v-model:value="ticket.passengerType" style="width: 100%">
            <!-- 不加:value的话 就会默认v-model绑定到{{item.desc}} 也就是选项的内容 所以需要指定才正确 -->
            <a-select-option v-for="item in PASSENGER_TYPE_ARRAY" :key="item.code" :value="item.code">
              {{item.desc}}
            </a-select-option>
          </a-select>
        </a-col>
        <a-col :span="3">
          <a-select v-model:value="ticket.seatTypeCode" style="width: 100%">
            <a-select-option v-for="item in seatTypes" :key="item.code" :value="item.code">
              {{item.desc}}
            </a-select-option>
          </a-select>
        </a-col>
      </a-row>
    </div>
    <div v-if="tickets.length > 0">
      <a-button type="primary" size="large" @click="finishCheckPassenger">提交订单</a-button>
    </div>

    <a-modal v-model:visible="visible" title="请核对以下信息"
             style="top: 50px; width: 800px"
             ok-text="确认" cancel-text="取消"
             @ok="handleOk">
      <div class="order-tickets">
        <a-row class="order-tickets-header" v-if="tickets.length > 0">
          <a-col :span="3">乘客</a-col>
          <a-col :span="15">身份证</a-col>
          <a-col :span="3">票种</a-col>
          <a-col :span="3">座位类型</a-col>
        </a-row>
        <a-row class="order-tickets-row" v-for="ticket in tickets" :key="ticket.passengerId">
          <a-col :span="3">{{ticket.passengerName}}</a-col>
          <a-col :span="15">{{ticket.passengerIdCard}}</a-col>
          <a-col :span="3">
          <span v-for="item in PASSENGER_TYPE_ARRAY" :key="item.code">
            <span v-if="item.code === ticket.passengerType">
              {{item.desc}}
            </span>
          </span>
          </a-col>
          <a-col :span="3">
          <span v-for="item in seatTypes" :key="item.code">
            <span v-if="item.code === ticket.seatTypeCode">
              {{item.desc}}
            </span>
          </span>
          </a-col>
        </a-row>
        <br/>
<!--        选座类型chooseSeatType：{{chooseSeatType}}-->

        <div v-if="chooseSeatType === 0" style="color: red;">
          您购买的车票不支持选座
          <div>12306规则：只有全部是一等座或全部是二等座才支持选座</div>
          <div>12306规则：余票小于一定数量时，不允许选座（本项目以20为例）</div>
        </div>
        <!-- 需要注意 只买一张票的时候只用显示一排就行 不用两排 -->
        <div v-else style="text-align: center">
          <a-switch class="choose-seat-item" v-for="item in SEAT_COL_ARRAY" :key="item.code"
                    v-model:checked="chooseSeatObj[item.code + '1']" :checked-children="item.desc" :un-checked-children="item.desc" />
          <div v-if="tickets.length > 1">
            <a-switch class="choose-seat-item" v-for="item in SEAT_COL_ARRAY" :key="item.code"
                      v-model:checked="chooseSeatObj[item.code + '2']" :checked-children="item.desc" :un-checked-children="item.desc" />
          </div>
          <div style="color: #999999">提示：您可以选择{{tickets.length}}个座位</div>
        </div>

<!--        <br/>-->
<!--        选座结构对象chooseSeatObj：{{chooseSeatObj}}-->
<!--        <br/>-->
<!--        现有的座位类型SEAT_COL_ARRAY：{{SEAT_COL_ARRAY}}-->
        <br/>
        最终购票信息:{{tickets}}
        <br/>
        选座结构对象chooseSeatObj：{{chooseSeatObj}}
      </div>
    </a-modal>
  </div>

</template>

<script>

import {computed, defineComponent, onMounted, ref, watch} from "vue";
import axios from "axios";
import {notification} from "ant-design-vue";

export default defineComponent({
  name: "orderView",
  setup() {
    /**
     * ticket.vue页面中 点击预定按钮后，会调用“toOrder”方法
     * 其中会将预定的票的信息存到session中
     * SessionStorage.set(SESSION_ORDER,dailyTrainTicket.value);
     * 所以dailyTrainTicket就可以理解成票的信息
     * @type {any|{}}
     */
    const dailyTrainTicket = SessionStorage.get(SESSION_ORDER) || {};
    console.log("下单的车次信息",dailyTrainTicket);
    const passengers = ref([]);
    const PassengerOptions = ref([]);
    const PassengerChecks = ref([]);
    const tickets = ref([]);
    const PASSENGER_TYPE_ARRAY = window.PASSENGER_TYPE_ARRAY;
    const visible = ref(false);

    const SEAT_TYPE = window.SEAT_TYPE;
    console.log(SEAT_TYPE)
    // 本车次提供的座位类型seatTypes，含票价，余票等信息，例：
    // {
    //   type: "YDZ",
    //   code: "1",
    //   desc: "一等座",
    //   count: "100",
    //   price: "50",
    // }
    // 关于SEAT_TYPE[KEY]：当知道某个具体的属性xxx时，可以用obj.xxx，当属性名是个变量时，可以使用obj[xxx]
    const seatTypes = [];
    for (let KEY in SEAT_TYPE) {
      let key = KEY.toLowerCase();
      /**
       * 在ticket.vue的setup方法中定义了dailyTrainTicket的结构 其中有 ydz edz rw等属性 所以变成小写以后就可以直接访问了
       */
      if (dailyTrainTicket[key] >= 0) {  // >=0表示有这个座位类型 负数表示不存在这种座位
        seatTypes.push({
          type: KEY, //比如一等座 ydz
          code: SEAT_TYPE[KEY]["code"],  //座位对应的那个编号 enums.js中可以看到结构
          desc: SEAT_TYPE[KEY]["desc"],
          count: dailyTrainTicket[key],  //说明ydz edz这种字段里存的是座位对应的数量
          price: dailyTrainTicket[key + 'Price'],  //源数据里是ydzPrice edzPrice ywPrice这种类型 所以这样读取
        })
      }
    }
    console.log("本车次提供的座位：", seatTypes);

    /**
     * 响应式变量chooseSeatType 0：不支持选座；1：选一等座；2：选二等座 用于辅助判断是否支持选座
     */
    const chooseSeatType = ref(0);
    // 根据选择的座位类型，计算出对应的列，比如要选的是一等座，就筛选出ACDF，要选的是二等座，就筛选出ABCDF

    //computed和watch类似 都可以用于响应式的计算一个数值 声明一个响应式变量
    const SEAT_COL_ARRAY = computed(() => {
      //用于过滤 SEAT_COL_ARRAY中座位类型等于chooseSeatType的座位类型的项目
      return window.SEAT_COL_ARRAY.filter(item => item.type === chooseSeatType.value);
    });
    // 选择的座位 一等座为例 初始构造两排然后都是false
    // {
    //   A1: false, C1: true，D1: false, F1: false，
    //   A2: false, C2: false，D2: true, F2: false
    // }
    /**
     * 这部分主要功能就是初始化两排座位 根据具体几等座位去初始化四个或者五个 以上面例子的结构存到chooseSeatObj里
     */
    const chooseSeatObj = ref({});
    watch(() => SEAT_COL_ARRAY.value, () => {
      /**
       * 核心BUG修复
       *  为了避免出现问题 当选择了二等座的B座位后又重新选择为一等座 导致B的选座为true从而影响一等座的选座数量问题
       *  以及出现赋值顺序不一致的问题 需要再座位设定之前先把所有选座信息清空  chooseSeatObj.value = {};
       */
      chooseSeatObj.value = {};
      for (let i = 1; i <= 2; i++) {
        //enums.js: SEAT_COL_ARRAY=[{code:"A",desc:"A",type:"1"},{code:"C",desc:"C",type:"1"},
        SEAT_COL_ARRAY.value.forEach((item) => {
          chooseSeatObj.value[item.code + i] = false;
        })
      }
      console.log("初始化两排座位，都是未选中：", chooseSeatObj.value);
    }, {immediate: true});

    const finishCheckPassenger = () => {
      console.log("购票列表", tickets.value);

      /**
       * 如果购买的票超过五张 不允许购买
       */
      if(tickets.value.length > 5) {
        notification.error({description: '最多只能购买5张车票'});
        return;
      }

      /**
       * 前端余票校验 缓解后端的压力
       * @type {any}
       */
      // 校验余票是否充足，购票列表中的每个座位类型，都去车次座位余票信息中，看余票是否充足
      // 前端校验不一定准，但前端校验可以减轻后端很多压力
      // 注意：这段只是校验，必须copy出seatTypesTemp变量来扣减，用原始的seatTypes去扣减，会影响真实的库存
      let seatTypesTemp = Tool.copy(seatTypes);
      for (let i = 0; i < tickets.value.length; i++) {
        let ticket = tickets.value[i];
        for (let j = 0; j < seatTypesTemp.length; j++) {
          let seatType = seatTypesTemp[j];
          // 同类型座位余票-1，这里扣减的是临时copy出来的库存，不是真正的库存，只是为了校验
          if (ticket.seatTypeCode === seatType.code) {
            seatType.count--;
            if (seatType.count < 0) { //减少以后已经小于0 说明之前就已经为0 票不够了 直接终止操作
              notification.error({description: seatType.desc + '余票不足'});
              return;
            }
          }
        }
      }
      console.log("前端余票校验通过");


      /**
       * 是否支持选座功能的判断
       * 判断是否支持选座，只有纯一等座和纯二等座支持选座 或者余票数量比如大于等于20才允许选座
       */
      let ticketSeatTypeCodes = [];
      for (let i = 0; i < tickets.value.length; i++) {
        let ticket = tickets.value[i];
        // 先筛选出购票列表中的所有座位类型，比如四张票：[1, 1, 2, 2] 两张一等座 两张二等座
        ticketSeatTypeCodes.push(ticket.seatTypeCode);
      }
      // 为购票列表中的所有座位类型去重：[1, 2]
      const ticketSeatTypeCodesSet = Array.from(new Set(ticketSeatTypeCodes));
      console.log("选好的座位类型：", ticketSeatTypeCodesSet);
      if (ticketSeatTypeCodesSet.length !== 1) {
        console.log("选了多种座位，不支持选座");
        chooseSeatType.value = 0;
      } else { // ticketSeatTypeCodesSet.length === 1，即只选择了一种座位（不是一个座位，是一种座位）
        if (ticketSeatTypeCodesSet[0] === SEAT_TYPE.YDZ.code) {
          console.log("一等座选座");
          chooseSeatType.value = SEAT_TYPE.YDZ.code;
        } else if (ticketSeatTypeCodesSet[0] === SEAT_TYPE.EDZ.code) {
          console.log("二等座选座");
          chooseSeatType.value = SEAT_TYPE.EDZ.code;
        } else {
          console.log("不是一等座或二等座，不支持选座");
          chooseSeatType.value = 0;
        }

        // 余票小于20张时，不允许选座，否则选座成功率不高，影响出票
        if (chooseSeatType.value !== 0) { //表明此时是经过前面的判断 允许选座 一等或者二等的情况 才去判断是否小于20张
          for (let i = 0; i < seatTypes.length; i++) {
            let seatType = seatTypes[i];
            // 找到同类型座位
            if (ticketSeatTypeCodesSet[0] === seatType.code) {
              // 判断余票，小于20张就不支持选座
              if (seatType.count < 20) {
                console.log("余票小于20张就不支持选座")
                chooseSeatType.value = 0;
                break;
              }
            }
          }
        }
      }

      //弹出确认页面
      visible.value = true;
    };

    watch(() => PassengerChecks.value, (newVal, oldVal)=>{
      console.log("勾选的乘客发生变化",newVal,oldVal);
      //每次有变化时 将购票列表清空 然后重新构造列表
      tickets.value = [];
      PassengerChecks.value.forEach((item) => tickets.value.push({
        passengerId: item.id,
        passengerType: item.type,
        seatTypeCode: seatTypes[0].code,
        passengerName: item.name,
        passengerIdCard: item.idCard
      }));
    }, {immediate: true});

    const HandleQueryPassengers = () => {
      axios.get("/member/passenger/queryById").then((response) => {
        let data = response.data;
        if(data.success){
          passengers.value = data.content;
          passengers.value.forEach((item) => PassengerOptions.value.push({
            label: item.name,
            value: item
          }))
        }else{
          notification.error({description:data.message});
        }
      });
    };

    onMounted(() => {
      HandleQueryPassengers();
    });

    const handleOk = () => {
      for(let i = 0; i < tickets.value.length; i++){
        tickets.value[i].seat = null;
      }
      let i = -1; //为-1表示不选座 否则就需要控制选座数量和真实票数量必须一致
      for(let key in chooseSeatObj.value){
        if(chooseSeatObj.value[key]){
          i++;
          if(i > (tickets.value.length -1)){
            notification.error({description:'所选择的座位数量大于购票数量！选票失败！'});
            return;
          }
          tickets.value[i].seat = key;
        }
      }
      if(i>-1 && i< (tickets.value.length -1)){
        notification.error({description:'当前选座数少于购票数，请重新选座，确保座位选择完整！'});
        return;
      }
      console.log("最终选票结果：",tickets.value);

      axios.post("/business/web/confirmOrder/confirm",{
        date : dailyTrainTicket.date,
        trainCode : dailyTrainTicket.trainCode,
        start : dailyTrainTicket.start,
        end : dailyTrainTicket.end,
        dailyTrainTicketId : dailyTrainTicket.id,
        tickets : tickets.value
      }).then((response) => {
        let data = response.data;
        if(data.success){
          notification.success({description:"下单成功！"});
        }else{
          notification.error({description: data.message});
        }
      });
    };

    return{
      dailyTrainTicket,
      seatTypes,
      passengers,
      PassengerOptions,
      PassengerChecks,
      tickets,
      PASSENGER_TYPE_ARRAY,
      visible,
      finishCheckPassenger,
      chooseSeatType,
      chooseSeatObj,
      SEAT_COL_ARRAY,  //返回的作用主要是为了后续chooseSeatObj做计算使用的
      handleOk
    };
  },
});

</script>

<style>
.order-train .order-train-main {
  font-size: 18px;
  font-weight: bold;
}
.order-train .order-train-ticket {
  margin-top: 15px;
}
.order-train .order-train-ticket .order-train-ticket-main {
  color: red;
  font-size: 18px;
}

.order-tickets {
  margin: 10px 0;
}
.order-tickets .ant-col {
  padding: 5px 10px;
}
.order-tickets .order-tickets-header {
  background-color: cornflowerblue;
  border: solid 1px cornflowerblue;
  color: white;
  font-size: 16px;
  padding: 5px 0;
}
.order-tickets .order-tickets-row {
  border: solid 1px cornflowerblue;
  border-top: none;
  vertical-align: middle;
  line-height: 30px;
}

.order-tickets .choose-seat-item {
  margin: 5px 5px;
}
</style>